import { NodeStatus } from "../NodeStatus";
import { INodeConfig } from "../interfaces/INodeConfig";
import { DecoratorNode } from "./DecoratorNode";


/**
 * 如果子节点执行后返回RUNNING，该节点返回RUNNING；
 * 如果子节点执行后返回SUCCESS，该节点返回SUCCESS，不再执行；
 * 如果子节点执行后返回FAILURE，该节点再次尝试执行子节点，直到尝试了num_attempts次；
 */
export class RetryNode<T> extends DecoratorNode<T> {

    private max_attempts_: number = 1;

    private try_index: number;

    constructor(name: string, blackboard: T) {
        super(name, blackboard);
        this.try_index = 0;
    }
    
    Init(data: INodeConfig): void {
        if (data.hasOwnProperty('num')) {
            // @ts-ignore
            this.max_attempts_ = data['num'];
        }
    }

    Halt() {
        this.try_index = 0;
        super.Halt();
    }

    Tick(): NodeStatus {
        this.status = NodeStatus.RUNNING;

        while (this.try_index < this.max_attempts_ || this.max_attempts_ == -1) {
            const child_state = this.GetChild()!.Evaluate();
            switch (child_state) {
                case NodeStatus.SUCCESS: {
                    this.try_index = 0;
                    this.HaltChild();
                    return NodeStatus.SUCCESS;
                }
                case NodeStatus.FAILURE:
                    {
                        this.try_index++;
                        this.HaltChild();
                    }
                    break;
                case NodeStatus.RUNNING: {
                    return NodeStatus.RUNNING;
                }
                default: {
                    throw new Error('A child node must never return IDLE');
                }
            }
        }

        this.try_index = 0;
        return NodeStatus.FAILURE;
    }
}
